<?php
/*
This file 'pps.php' is part of the PPS project <http://code.google.com/p/fracsnetpps/>

Copyright: (C) 2009 Arthur, B. aka ]{ing <whinemore@gmail.com>

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.
 .
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 GNU General Public License for more details.
 .
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 .

*/
$INFO= array();

include "refresh.php";
include "pps_player.php";
include "pps_base.php";
require ("ppsconfig.php");

class pps{

	/* General info */
	private	$m_ip;
	private $m_port;
	private $m_adminlog;
	private $m_sock;

	/* Database info */
	private $m_pps_db;
	private $m_db_ip;
	private $m_db_pass;
	private $m_db_user;
	private $m_db_name;

	/* Stats info */
	private $m_buffer;
	private $stats;
	private $m_connected;
	
	/* Number of players needed to rate */
	private $m_rate;
	private $m_start;
	private $m_version;
	
	/* Use echo-mode */
	private $m_printc_kills;
	private $m_prints_general;
	private $m_printc_general;
	
	private $m_debug;
	
	/* IRC-mode Variables : Not REALLY needed */
	private $m_irc;
	private $m_bufferi;
	private $m_socki;
	private $m_printi;
	
/* ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */	
        /*  ************************************************************** 
           * Function: PPS class construct( public )                      *
           * Parameters:                                                  *
           *  -- Name --------- Purpose --------------------- default --  *
           * |  s_ip    - Soldat server adress         -   'localhost'  | *
           * |  s_port  - ... server port              -      20202     | *
           * |  s_pass  - ... server adminlog          -      'pps'     | *
           * |  db_ip   - 'pps' database adress        -   'localhost'  | *
           * |  db_pass - ... password                 -      empty     | *
           * |  db_user - ... user                     -      'root'    | *
           * |  db_name - ... database name            -      'pps'     | *
           * |  debug   - 'debug' mode : boolean       -       true     | *
           * |  rate_at - minimum players required     -        1       | *
           * |  silent  - 'silent' mode : boolean      -       true     | *
           * |  irc_adm - 'irc admin' mode : boolean   -       true     | *
           *  ----------------------------------------------------------  *
           * Note: Make your info is correct, this function does no       *
           * variable checking!                                           *
            **************************************************************  */
           
        public function __construct(    $s_ip           = "localhost",          
                                        $s_port         = "20202", 
                                        $s_pass         = "malice",
                                        $db_ip          = "localhost", 
                                        $db_pass        = "", 
                                        $db_user        = "root" , 
                                        $db_name        = "pps", 
                                        $debug          = true, 
                                        $rate_at        = 0, 
                                        $silent         = true, 
                                        $irc_adm        = true){

										
/* ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */									
	$this->m_start = time();
	$this->m_version = "v0.5.5 updated(05/05/09)";
	$this->m_rate = $rate_at;
	$this->m_debug = $debug;
        $this->m_ip = $s_ip;
        $this->m_port = $s_port;
        $this->m_adminlog = $s_pass;
        
        $this->m_connected = false;
        
        $this->m_db_ip = $db_ip;
        $this->m_db_pass = $db_pass;
        $this->m_db_user = $db_user;
        $this->m_db_name = $db_name;

		
		/*NOTE: Printing kills should probably never be used anymore, kill code is solid at this point */
		if( $silent )
		{
			$this->m_printc_kills = false;
			$this->m_printc_general = false;
			$this->m_prints_general = false;
		}else{
			if( $debug )
			{
				$this->m_printc_kills = false;
				$this->m_printc_general = true;
				$this->m_prints_general = true;
			}
		}
		
		if( $irc_adm && $debug )
		{
			$this->m_printi = true;
			$this->m_irc	= true;
		}
	}
	
	function __destruct(){
		mysqli_query($this->m_pps_db, "UPDATE status SET stats_on=0 WHERE stats_version='v0.4b'");
        mysqli_close($this->m_pps_db);
	}
/* ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */	
	private function get_refresh(){
/* ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */	
		fputs($this->m_sock, "REFRESH\r\n");
		while( $this->m_buffer != "REFRESH" ){
			$this->m_buffer = trim(fgets($this->m_sock, 1024));
			if( !$this->m_buffer ) continue;
			else if($this->m_buffer == "REFRESH") break;
		}
		
		return GetSoldatInfo($this->m_sock);
	}
/* ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */	
	public function pps_connect(){
/* ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
		echo "--> Connecting..";
        $this->m_sock = fsockopen($this->m_ip, $this->m_port);
        echo ".";
		if(!($this->m_sock) ){
			echo "Unable to connect to ip: $this->m_ip on port: $this->m_port <br>";
			exit();
		}else{
			$admin = "$this->m_adminlog\r\n";
			fputs($this->m_sock, $admin);
			$this->m_pps_db = new mysqli($this->m_db_ip, $this->m_db_user, $this->m_db_pass, $this->m_db_name);
            echo ".";
			if( !($this->m_pps_db) ){
				echo "Unable to connect to the database<br>\n";
				exit();
			}
			
			$this->m_connected = true;
            echo ". OK\n";
			
		}
	}
/* ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
	private function f__init_irc(){	/* 	*****************************************
										* Connect to irc..(quakenet) #g.bt		*
										* TODO: get rid of some hard coded stuff*
										* add error checking					*
										***************************************** */
/* ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */			
	}	
/* ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
	public function pps_monitor(){		/*******************************************************
										 * 	Main monitoring function PROXY will setup          *
										 *	the enviornment and load mode apropriate functions *
										 *******************************************************/
/* ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
		if(!$this->m_connected) return;
		
		set_time_limit(0);
		
		$this->m_buffer = '';
		
		
		$this->stats = new base_stats($this->m_pps_db, $this->m_sock, $this->m_buffer, $this->get_refresh());
		
		mysqli_query($this->m_pps_db, "UPDATE status SET stats_on=1 WHERE stats_version='v0.4b'");
		
		/*if( $this->m_prints_general )
		{
			fputs($this->m_sock, "/say Progressive Play Statistics bot has connected sucessfully!\r\n");
			fputs($this->m_sock, "/say This server is now being monitored\r\n");
		}*/
		echo "--> Now monitoring...\n";
		if( $this->m_debug ) 
			$this->f_dbg_monitor();
		else
			$this->f_monitor();
	
		fclose($this->m_sock);
		
		echo "Ubnormal Termination => 'connection lost'\n\r";
		$this->m_is_connected = false;
	}

/* ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */	
	private function f_handle_irc(){
/* ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
		/*if( strpos($this->m_bufferi, "PING" !== false ) )
		{
			$this->_irc_handle_ping();
			return false;
		}
		
		if( strpos($this->m_bufferi, ":!" ) )
		{
			$irc_command = substr($this->m_bufferi, strpos($this->m_bufferi, ":!") + 2);
			if( $irc_command == "setprint_1" )
				$this->m_printi = false;
			elseif( $irc_command == "setprint_0" )
				$this->m_printi = true;
			elseif( $irc_command == "help" )
				fputs($this->m_socki, ": PRIVMSG #fracs_pub :commands - !setprint_(1/0), !sinfo, !binfo, !pinfo | soldat command = replace '/' with `\r\n");
			elseif( $irc_command == "binfo" )
			{
				fputs($this->m_socki, ": PRIVMSG #fracs_pub :version " . $this->m_version . " | running for ". (time() - $this->m_start) . " seconds \r\n");
				if( $this->m_debug )
					fputs($this->m_socki, ": PRIVMSG #fracs_pub :Debug-mode is ON\r\n");
				else
					fputs($this->m_socki, ": PRIVMSG #fracs_pub :Debug-mode is OFF\r\n");
			}
			elseif( $irc_command == "sinfo" )
			{
				stream_set_blocking($this->m_sock, true);
				$refresh = $this->get_refresh();
				fputs($this->m_socki, ": PRIVMSG #fracs_pub :".$this->m_ip . ":". $this->m_port . " -- (" . $refresh['players'] . "/12) -- ". $refresh['map'] . " -- " . $refresh['team'][1].":".$refresh['team'][2] ."\r\n");
				stream_set_blocking($this->m_sock, false);
				return true;
			}
			elseif( $irc_command == "quit" )
			{
				fputs($this->m_socki, ": QUIT : pps stats(". $this->m_version . ") by King for the community\r\n");
				exit();
			}
			elseif( $irc_command == "pinfo" )
			{
				stream_set_blocking($this->m_sock, true);
				$refresh = $this->get_refresh();
				if( $refresh['players'] )
				{
					$plr = "| ";
					for( $i = 0; $i < $refresh['players'] ; $i++ )
						$plr = $plr . "[". $refresh['player'][$i]['id'] . "]" . $refresh['player'][$i]['name'] . "(". $refresh['player'][$i]['ip'] . ")" . " | ";
					fputs($this->m_socki ,": PRIVMSG #fracs_pub :". $plr . "\r\n");
				}else{
					fputs($this->m_socki, ": PRIVMSG #fracs_pub :zero players found in ". $this->m_ip . ":" . $this->m_port . "\r\n");
				}
				stream_set_blocking($this->m_sock, false);
				return true;
			}
			return false;
		}
		if( strpos($this->m_bufferi, ":`" ) )
		{
			$soldat_command = substr($this->m_bufferi, strpos($this->m_bufferi, ":`") + 2);
			$soldat_command = "/" . $soldat_command . "\r\n";
			fputs($this->m_sock, $soldat_command );
			return true;
		}
		return false;
			*/
	}
/* ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
	private function f_dbg_monitor(){
	/* Debug Mode Monitoring function, echoes all info allowed */
/* ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
		
		/* Beh... sorta a copy->paste of v0.3 code */
		$bench = 0;
		do{
			
			$this->m_buffer = trim(fgets($this->m_sock, 1024));
			if( !$this->m_buffer ) continue;
			//echo $this->m_buffer, "\n";
			$bench = microtime();
			
			if( substr($this->m_buffer, 0, 5) == "PLEFT" ){
                $this->stats->ch_left();
            }
			elseif( strpos($this->m_buffer, "joining game (") )
			{ /* Player is trying to join, so lets grab their ip */
				$start = strpos( $this->m_buffer, "joining game (");
				$start+= 14;
				$end = strpos( $this->m_buffer, ":" , $start);
				$join_try = substr( $this->m_buffer, $start, ($end - $start));
                //$new_pass = mt_rand(mt_rand(20, 100), 1000);
                //fputs($this->m_sock, "/password $new_pass\r\n");
			}
			elseif( substr($this->m_buffer, 0, 5) == "PJOIN") /* This works with the help of the server side script */
			{
				$ret = $this->stats->ch_join($join_try);
				$bench = microtime() - $bench;
				$join_try = null;
				if( $this->m_printc_general && $ret )
				{
					echo "DEBUG: <player join> ", $ret , ", pc = ", $this->stats->pc , " benchmark =>", $bench , "\n";
				}
			}
							/* Kills and Deaths */
			elseif( strpos($this->m_buffer, "killed (") ){
				$ret = $this->stats->ch_kill(); 
				$bench = microtime() - $bench;
				if( $this->m_printc_kills && $ret) 
				{
					echo "DEBUG: <kill> ". $ret , " bench =>", $bench , "\n";
				}
			}				/* Grabs */
			elseif( strpos($this->m_buffer, "captured the") )
			{
				$ret = $this->stats->ch_grab();
                $bench = microtime() - $bench;
                if( $this->m_printc_general && $ret )
                    echo "DEBUG: <grab> $ret benchmark => $bench \n";
			}
								/* Caps */
			elseif( strpos($this->m_buffer, "scores for") )
			{
				$ret = $this->stats->ch_cap();
				$bench = microtime() - $bench;
				if( $this->m_printc_general && $ret )
				{	
					echo "DEBUG: <cap> " , $ret , " benchmark =>", $bench , "\n";
				}
			}
			elseif( strpos($this->m_buffer, "returned the") ) 
			{
				$ret = $this->stats->ch_return();
				$bench = microtime() - $bench;
				if( $this->m_printc_general && $ret )
				{
					echo "DEBUG: <return> " , $ret , " benchmark =>", $bench , "\n";
				}
			}
			elseif( substr($this->m_buffer, 0, 9) == "Next map:" )
			{

                $this->stats->ch_nextmap();
                $bench = microtime() - $bench;
                if( $this->m_printc_general )
                    echo "DEBUG: <next map> updating stats, pc = " , $this->stats->pc , " benchmark =>", $bench , "\n";
				
			}
            elseif( substr($this->m_buffer,0,8) == "/quitpps" )
            {
                exit();
            }
            elseif( strpos($this->m_buffer, "!rating") ){
                $name = substr($this->m_buffer, 1, strpos($this->m_buffer, "!rating") - 3);
                echo $name, "\n";
                if( array_key_exists($name, $this->stats->T->ps) ){
                    $P = &$this->stats->T->ps[$name];
                    if( $P->rating ){
                        $rating = round($P->rating, 2);
                    }else{
                        $rating = round($P->mu - ($P->sigma * 2.5), 2);
                    }
                    fputs($this->m_sock, "/say ". $P->acc_name . "'s rating: $rating\r\n");
                }
            }
		}while(!feof($this->m_sock));
	}
	
	private function f_monitor(){
	/* Live Monitoring function, runs with no debugging output or commands */
		$join_try = "";
	
		do
		{
		
			$this->m_buffer = trim(fgets($this->m_sock, 1024));
			if( !$this->m_buffer ) continue;
			
			/* Grab players ip that is trying to join */
			if( strpos($this->m_buffer, "joining game (") )
			{
				$start = strpos($this->m_buffer, "joining game (") + 14;
				$join_try = substr( $this->m_buffer, $start, (strpos($this->m_buffer, ":", $start) - $start));
				continue;
			}
			/* Check if the a player joined */
			if( strpos($this->m_buffer, "has joined") )
			{
				$this->stats->ch_join($join_try);
				$join_try = "";
                continue;
			}
			/* Failsafe */
            if( substr($this->m_buffer,0,9) ==  "/failsafe" )
            {
                echo "Failsafe\n";
                break;
            }
			if( $this->stats->pc > $this->ratings_start ) /* Rate only when ... how many people in the server ? default: >0 */
			{
                if( strpos($this->m_buffer, "has left") )
                    $this->stats->ch_left(0);
                elseif( strpos($this->m_buffer, "has been kicked") )
                    $this->stats->ch_left(1);
                elseif( strpos($this->m_buffer, "could not respond") )
                    $this->stats->ch_left(2);
                elseif( substr($this->m_buffer, 0, 5) == '[acc]' )
                    $this->stats->hook_accuracy();
                /* Kills and Deaths */
				elseif( strpos($this->m_buffer, "killed (") )
					$this->stats->ch_kill(); 
				/* Grabs */
				elseif( strpos($this->m_buffer, "captured the") )
					$this->stats->ch_grab();
				/* Caps */
				elseif( strpos($this->m_buffer, "scores for") )
					$this->stats->ch_cap();
				/* Returns */
				elseif( strpos($this->m_buffer, "returned the") ) 
					$this->stats->ch_return();
				/* Nextmap */
				elseif( substr($this->m_buffer, 0, 9) == "Next map:" )
					$this->stats->ch_nextmap();
				
			}else{	
				continue;
                echo "Nothing to be done.\n";
			}
		}while( !feof($this->m_sock) );
		
	}
}

$test = new pps($SOLDAT_SERVER,$SOLDAT_PORT,$SOLDAT_ADMLOG,$MYSQL_SERVER,$MYSQL_PASSWORD,$MYSQL_USER,$MYSQL_DB,true,0,true,false );


$test->pps_connect();
$test->pps_monitor();

?>